import characters.Ball;
import characters.Player;

import java.io.*;

public class Analyzer implements Runnable {
  static String rcgAddress;
  static String rclAddress;
  static String tableName = "GameData";

  String taskName;
  static DBUtil myDB;

  public Analyzer(String rcg, String rcl, String fileName) {
    rcgAddress = rcg;
    rclAddress = rcl;
    taskName = fileName;
    myDB = new DBUtil(tableName);
  }

  @Override
  public void run() {
    File output = new File("output/");
    if (!output.exists()) {
      output.mkdirs();
    }
    String outputPath = "output/" + taskName + ".db";
    if (myDB.setConnection("jdbc:sqlite:" + outputPath)) {
      MainDialog.infoWorkState(taskName + ": RCG stage Start;");
      RCGFileInput(rcgAddress);
      MainDialog.infoWorkState(taskName + ": RCG stage End;");
      myDB.excute("CREATE INDEX cycle_object on " + tableName + " (cycle, object);");
      MainDialog.infoWorkState(taskName + ": RCL stage Start;");
      RCLFileInput(rclAddress);
      MainDialog.infoWorkState(taskName + ": RCL stage End;");
    } else {
      MainDialog.warningWorkState(taskName + ": Create " + outputPath + " failed, table existed;");
      myDB.endConnection();
      return;
    }
    myDB.endConnection();
    MainDialog.infoWorkState(taskName + ": Task Completed;");
    return;
  }

  static String teamLeft = "";
  static String teamRight = "";

  static void setTeamLeft(String teamName) {
    teamLeft = teamName;
  }

  static void setTeamRight(String teamName) {
    teamRight = teamName;
  }

  protected static void RCGFileInput(String inputPath) {
    String line;
    String playMode = null;
    int cycle = 0;
    try {
      InputStream getStock = new FileInputStream(inputPath);
      Reader readStock = new InputStreamReader(getStock);
      BufferedReader bufferedReader = new BufferedReader(readStock);
      String [] tmp;
      while ((line = bufferedReader.readLine()) != null) {
        if (line.contains("playmode")) {
          tmp = line.split("\\(| |\\)");
          playMode = tmp[tmp.length - 1];
        } else if (line.contains("team ") && !line.contains("server_param")) {
          tmp = line.replaceAll("\\(|\\)", "").split("\\s+");
          setTeamLeft(tmp[2]);
          setTeamRight(tmp[3]);
        } else if (line.contains("show")) {
            tmp = line.substring(1, line.length() - 1).split("\\(\\(");
            for (int i = 0; i < tmp.length; i++) {
                if (tmp[i].startsWith("show")) {
                  cycle = Integer.parseInt(tmp[i].substring(tmp[i].indexOf(" ")).trim());
                  continue;
                } else if (tmp[i].startsWith("b")) {
                  Ball ball = new Ball(tmp[i]);
                  String sql = "INSERT INTO " + tableName + " (cycle, playMode, object, posX, posY, vecX, vecY) " +
                          " VALUES (" + cycle + ",\'" + playMode + "\',\'b\'," + ball.getPosX() + "," + ball.getPosY() + "," +
                          ball.getVecX() + "," + ball.getVecY() + ");";
                  myDB.excute(sql);
                  continue;
                } else if (tmp[i].startsWith("l") | tmp[i].startsWith("r")) {
                  Player player = new Player(tmp[i]);
                  String sql = "INSERT INTO " + tableName + " (cycle, playMode, object, type, posX, posY, vecX, vecY, bodyDir, neckDir, stamina, focusObject) " +
                          " VALUES (" + cycle + ",\'" + playMode + "\',\'" + player.getName() + "\',\'" + player.getType() + "\'," +
                          player.getPosX() + "," + player.getPosY() + "," + player.getVecX() + "," + player.getVecY() + "," +
                          player.getBodyDir() + "," + player.getNeckDir() + "," + player.getStamina() + ",\'" + player.getFocusObject() + "\');";
                  myDB.excute(sql);
                }
            }
        }
      }
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  protected static void RCLFileInput(String inputPath) {
    String line;
    String playMode = "kick_off_l";
    int cycle;
    try {
      InputStream getStock = new FileInputStream(inputPath);
      Reader readStock = new InputStreamReader(getStock);
      BufferedReader bufferedReader = new BufferedReader(readStock);
      String[] tmp;
      while ((line = bufferedReader.readLine()) != null) {
        if (!line.startsWith("0")) {
          if (line.contains("referee")) {
            tmp = line.split("\\(");
            cycle = Integer.parseInt(tmp[0].substring(0, tmp[0].indexOf(",")));
            tmp[1] = tmp[1].replaceAll("\\(|\\)", "").trim();
            playMode = tmp[1].substring(tmp[1].indexOf(" ") + 1);
            continue;
          } else if (line.contains("Recv")) {
            tmp = line.split(": ");
            String[] tmp1;
            String object;
            String objectTeam;
            String objectNum;

            tmp1 = tmp[0].split("\\t|\\s+");
            cycle = Integer.parseInt(tmp1[0].substring(0, tmp1[0].indexOf(",")));
            objectTeam = tmp1[2].substring(0, tmp1[2].lastIndexOf("_"));
            objectNum = tmp1[2].substring(tmp1[2].lastIndexOf("_") + 1);
            if (teamLeft.equals(objectTeam)) {
              object = "l " + objectNum;
            } else if (teamRight.equals(objectTeam)) {
              object = "r " + objectNum;
            } else {
              System.out.println("ERROR: Unexpected object: " + tmp1[2]);
              continue;
            }

            String sql = "UPDATE " + tableName + " set actions = \'" + tmp[1] + "\' WHERE cycle = " + cycle + " AND object = \'" + object + "\';";
            myDB.excute(sql);
            continue;
          }
        }
      }
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

}
